/*
 * Copyright 2006 Google Inc.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.google.gwt.user.rebind;

import com.google.gwt.core.ext.GeneratorContext;
import com.google.gwt.core.ext.TreeLogger;

import java.io.PrintWriter;

// TODO: maybe add a "comment mode"
class ClassSourceFileComposer implements SourceWriter {

  private final PrintWriter fPrintWriter;
  private int fIndent;
  private boolean fAtStart;
  private final GeneratorContext fCtx;

  ClassSourceFileComposer(GeneratorContext ctx, PrintWriter printWriter, String targetPackageName,
      String targetClassShortName, String superclassName,
      String[] interfaceNames, String[] imports) {
    fCtx = ctx;
    fPrintWriter = printWriter;

    writeFileHeader(targetPackageName, targetClassShortName, superclassName,
      interfaceNames, imports);
  }

  private void writeFileHeader(String targetPackageName,
      String targetClassShortName, String superclassName,
      String[] interfaceNames, String[] imports) {
    println("package " + targetPackageName + ";");
    println();
    if (imports != null && imports.length > 0) {
      for (int i = 0, n = imports.length; i < n; ++i) {
        println("import " + imports[i] + ";");
      }
      println();
    }
    print("public class " + targetClassShortName);
    if (superclassName != null)
      print(" extends " + superclassName);
    if (interfaceNames != null && interfaceNames.length > 0) {
      print(" implements ");
      for (int i = 0, n = interfaceNames.length; i < n; ++i) {
        if (i > 0)
          print(", ");
        print(interfaceNames[i]);
      }
    }
    println(" {");

    indent();
  }

  public void commit(TreeLogger logger) {
    outdent();
    println("}");
    fPrintWriter.close();
    fCtx.commit(logger, fPrintWriter);
  }

  public void outdent() {
    --fIndent;
  }

  public void indent() {
    ++fIndent;
  }

  public void print(String s) {
    // If we just printed a newline, print an indent.
    //
    if (fAtStart) {
      for (int j = 0; j < fIndent; ++j)
        fPrintWriter.print("    ");
      fAtStart = false;
    }

    // Now print up to the end of the string or the next newline.
    //
    String rest = null;
    int i = s.indexOf("\n");
    if (i > 0 && i < s.length() - 1) {
      rest = s.substring(i + 1);
      s = s.substring(0, i + 1);
    }

    fPrintWriter.print(s);

    // If rest is non-null, then s ended with a newline and we recurse.
    //
    if (rest != null) {
      fAtStart = true;
      print(rest);
    }
  }

  public void println(String s) {
    print(s + "\n");
    fAtStart = true;
  }

  public void println() {
    print("\n");
    fAtStart = true;
  }

  public void indentln(String s) {
    indent();
    println(s);
    outdent();
  }
}
